/* Copyright (c) 2004-2008, Andriy Nikolov
 * All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package org.processmining.email;

import java.util.*;

/**
 * <p>Represents the data for the User-Task diagram.
 *
 * @author Andriy Nikolov
 * @version 1.0
 */
public class TaskPersonTable {
  Vector taskList, personList;
  ProcessLog processLog;
  double normalizedWeights[][];
  int absoluteWeights[][];
  boolean peopleConnected[];
  boolean showOnlyOriginators = false;

  public TaskPersonTable() {
    jbInit();
  }

  public TaskPersonTable(ProcessLog log) {
    processLog = log;
    jbInit();
  }

  public ProcessLog getProcessLog() {
    return processLog;
  }

  public void setProcessLog(ProcessLog log) {
    processLog = log;
  }

  private void jbInit() {
    taskList = new Vector();
    personList = new Vector();
  }

  public Vector getTaskList() {
    return taskList;
  }

  public Vector getPersonList() {
    return personList;
  }

  public void setShowOnlyOriginators(boolean value) {
    showOnlyOriginators = value;
  }

  private void getAllTasks() {
    Vector taskTypesList;
    ProcessTaskType curType;
    String curName;

    taskList.clear();
    taskTypesList = processLog.getTaskTypesList();
    for(int i=0;i<taskTypesList.size();i++) {
      curType = (ProcessTaskType)taskTypesList.get(i);
      curName = (String)curType.getName();
      taskList.add(curName);
    }
  }

  private void getAllPeople() {
    EMailRecipient currentPerson;
    EMailLog eMailLog;
    personList.clear();
    eMailLog = processLog.getEMailLog();
    for(int i=0;i<eMailLog.getEmployeesList().size();i++) {
      currentPerson = (EMailRecipient)eMailLog.getEmployeesList().get(i);
      if(currentPerson.isActive()) {
        personList.add(currentPerson.getName());
      }
    }
  }

  private void calculateWeights() {
    ProcessCase currentCase;
    ProcessEvent currentEvent;
    ProcessTask currentTask;
    EMailMessage currentMessage;
    EMailRecipient currentRecipient;
    int i, j, k;

    absoluteWeights = new int[taskList.size()][personList.size()];
    peopleConnected = new boolean[personList.size()];
    for(i=0;i<taskList.size();i++) {
      for(j=0;j<personList.size();j++) {
        absoluteWeights[i][j] = 0;
      }
    }
    for(i=0;i<personList.size();i++) {
      peopleConnected[i] = false;
    }
    for(i=0;i<processLog.getOrderedCaseList().size();i++) {
      currentCase = (ProcessCase)processLog.getOrderedCaseList().get(i);
      for(j=0;j<currentCase.getEventList().size();j++) {
        currentEvent = (ProcessEvent)currentCase.getEventList().get(j);
        currentTask = (ProcessTask)currentEvent.getTask();
        currentMessage = (EMailMessage)currentEvent.getEMailMessage();
        if(currentMessage==null)
          continue;
        currentRecipient = currentMessage.getFrom();
        incWeight(currentTask.getType().getName(), currentRecipient.getName());
        if(!showOnlyOriginators) {
          for (k = 0; k < currentMessage.getTo().size(); k++) {
            currentRecipient = (EMailRecipient) currentMessage.getTo().get(k);
            incWeight(currentTask.getName(), currentRecipient.getName());
          }
          for (k = 0; k < currentMessage.getCc().size(); k++) {
            currentRecipient = (EMailRecipient) currentMessage.getCc().get(k);
            incWeight(currentTask.getType().getName(), currentRecipient.getName());
          }
          for (k = 0; k < currentMessage.getBcc().size(); k++) {
            currentRecipient = (EMailRecipient) currentMessage.getBcc().get(k);
            incWeight(currentTask.getType().getName(), currentRecipient.getName());
          }
        }
      }
    }
  }

  private void normalizeWeights() {
    int max;
    int i, j;
    normalizedWeights = new double[taskList.size()][personList.size()];
    max = 1;

    for(i=0;i<taskList.size();i++) {
      for(j=0;j<personList.size();j++) {
        if(absoluteWeights[i][j]>max) {
          max = absoluteWeights[i][j];
        }
      }
    }
    for(i=0;i<taskList.size();i++) {
      for (j = 0; j < personList.size(); j++) {
        normalizedWeights[i][j] = absoluteWeights[i][j];
        normalizedWeights[i][j] /= max;
      }
    }
  }

  private void incWeight(String taskName, String personName) {
    int indexTask, indexPerson;
    try {
      indexTask = taskList.indexOf(taskName);
      indexPerson = personList.indexOf(personName);
      absoluteWeights[indexTask][indexPerson]++;
      peopleConnected[indexPerson] = true;
    } catch (IndexOutOfBoundsException e) {
      System.err.println(taskName);
      System.err.println(personName);
    }
  }

  /**
   * Calculates the weights of the diagram.
   */
  public void calculateTable() {
    getAllTasks();
    getAllPeople();
    calculateWeights();
    normalizeWeights();
  }

  public int getAbsoluteWeight(int taskNum, int personNum) {
    return absoluteWeights[taskNum][personNum];
  }

  public double getNormalizedWeight(int taskNum, int personNum) {
    return normalizedWeights[taskNum][personNum];
  }

  public int getAbsoulteWeight(String taskName, String personName) {
    try {
      return absoluteWeights[taskList.indexOf(taskName)][personList.indexOf(personName)];
    } catch(Exception e) {
      e.printStackTrace();
      return 0;
    }
  }

  public double getNormalizedWeight(String taskName, String personName) {
    try {
      return normalizedWeights[taskList.indexOf(taskName)][personList.indexOf(personName)];
    } catch(Exception e) {
      e.printStackTrace();
      return 0;
    }
  }

  public boolean isPersonConnected(String personName) {
    try {
      return peopleConnected[personList.indexOf(personName)];
    } catch(Exception e) {
      e.printStackTrace();
      return false;
    }
  }

}
